package Manejadores;

import Excepciones.FechaIncorrectaException;
import Excepciones.FechaInferiorException;
import Logica.Accion;
import Logica.Comentario;
import Logica.HistorialEstado;
import Logica.Reunion;
import Logica.Usuario;
import Persistencia.ADOAccion;
import Persistencia.ADOComentario;
import Persistencia.ADOHistorialEstado;
import Persistencia.ADOReunion;
import Persistencia.ADOUsuario;
import UI.IActualizarAccion;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Date;

/**
 *
 * @author NachoB
 * Esta clase contiene toda la logica que utilizara la interfaz para operar con los objetos correspondientes.
 */
public class ManejadorActualizarAccion {

    Accion actAccion = new Accion();
    IActualizarAccion iaa;
    ADOAccion ado = new ADOAccion();
    ADOComentario adocom;
    private LinkedList<Comentario> comentar = new LinkedList();

    public ManejadorActualizarAccion() {}

    //metodo para actualizar el estado y agregar comentarios. De vuelve true si fue satisfactoria la actualizacion, en caso contrario false.
    public boolean actualizar(int id_accion, int estado, int estadoAnterior, String nombreAccion, String usuario, String fecha, String descripcion, String reunion)
            throws FechaIncorrectaException, Exception {

        Usuario usu;
        //Un try para capturar excepciones en el momento de guardar comentarios y actualizar estado
        try {
            this.validarLongitudFecha(fecha);//valido la longitud
            this.validarDiasMesFecha(fecha);//valido los dias
            //la fecha es semanticamente correcta, se la agrego a la accion para faliciar la validez conta la actual       
            
            usu = new Usuario();//creo un usuario necesario ya que accion necesita de un usuario.
            usu.setNombreUsuario(usuario);      
            
            actAccion.setId(id_accion);//Creo objeto Accion y le doy los atributos que deseo modificar y el id_accion (para reconocer la accion)
            actAccion.setEstado(estado);
            actAccion.setNombre(nombreAccion);
            actAccion.setUsuario(usu);
            actAccion.setFechaVencimiento(fecha);
            actAccion.setDescripcion(descripcion);
            actAccion.setReunion(reunion);
            
            iaa = new IActualizarAccion();
            if(estado!=estadoAnterior)
            {
                if(estado==0){
                    cerrarAccionActualizarHistorial(actAccion);}
                if(estado==1){
                    abrirAccionNuevoHistorial(actAccion, usu);}
            }
            
            //Con el objeto ADOAccion llamo al metodo que actualizara el estado pasando la Accion antes creada
            ado.actualizarAccion(actAccion);                
            //metodo que inserta comentarios a la base de datos.
            if (comentarioAccion()) {
                //try que evita colisiones cuando no se cargaron comentarios y se desea solo cambiar el estado.
                try {
                    //limpio la lista una vez ya guardada en la base.
                    limpiarLista();
                    return true;
                } catch (Exception e) { return false; }
            } 
            else {
                return false;
            }            
            
        } catch (Exception e) {
            return false;
        }
    }

    //metodo que agrega comentarios a la linkedlist de comentarios, devuelve un String con el contenido de la descripcion de los comentarios de la lista.
    public String agregarComentario(String textoComentario, int id_accion) {
        //creo un comentario con un codigo de accion y le agrego la descripcion.        
        Comentario comenta = new Comentario();
        comenta.setIdAccion(id_accion);
        comenta.setDescripcion(textoComentario);
        iaa = new IActualizarAccion();
        actAccion.setId(iaa.getCodAccion());
        //agrego un comentario a la lista.
        if (addComentario(comenta)) //devuelve al metodo que retorna un String con la descripcion de los comentarios de la lista.
        {
            return mostrarListaComentario();
        } //txtaColeccion.setText(txtaColeccion.getText()+ "\n" + txtaComentario.getText());
        else {
            return "";
        }
    }

    public LinkedList<Comentario> getComentario() {
        return comentar;
    }

    public void setComentarios(LinkedList comentarios) {
        this.comentar = comentarios;
    }

    public boolean addComentario(Comentario com) {
        //return getComentario().add(com);
        return comentar.add(com);
    }

    public void limpiarLista() {
        comentar.clear();
    }

    public Iterator iterUsuarios(String proy) {
        ADOUsuario adusr = new ADOUsuario();
        Iterator iter = adusr.traerUsuariosPorProyectoHabilitados(proy).iterator();
        return iter;
    }
    
    public Iterator iterReunion(String proy){
        ADOReunion adore = new ADOReunion();
        Iterator iter = adore.obtenerReunionesPorProyecto(proy).iterator();
        return iter;
    }

    //Metodo que recorre la coleccion de comentarios llamando a un metodo que los inserta en la base de datos.
    public boolean comentarioAccion() {
        adocom = new ADOComentario();
        Iterator iter = comentar.iterator();
        Comentario com = null;
        try {
            while (iter.hasNext()) {
                com = (Comentario) iter.next();
                //Recorro la lista de comentarios para ir insertando cada uno de ellos en la BD con el metodo insertarComentario(com)
                adocom.insertarComentario(com);
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    //Metodo que devuelve un String con la descripcion de todos los comentarios de la coleccion.
    public String mostrarListaComentario() {
        Iterator iter = comentar.iterator();
        Comentario com = null;
        String cadena = "";
        int numerin = 0;
        //Recorro la lista de comentarios y voy almacenandolos en un string para mostrar por pantalla todos los comentarios agregados hasta el momento.
        while (iter.hasNext()) {
            numerin++;
            com = (Comentario) iter.next();
            cadena += "Comentario " + numerin + ": " + com.getDescripcion() + "\n";
        }
        return cadena;
    }
    
    public String getComentarios(int id_accion)
    {        
        ADOComentario adoc=new ADOComentario();
        String cadena;
        if(!adoc.buscarComentario(id_accion).equals(""))
            cadena="Comentarios Actuales \n\n" + adoc.buscarComentario(id_accion);
        else
            cadena="Comentarios Actuales \n\n" + "Esta accion no tiene comentarios";
        return cadena;
    }
    
    public void cerrarAccionActualizarHistorial(Accion a){
        HistorialEstado he = new HistorialEstado();
        he.setIdAccion(a.getId());
        he.setFechaCierre(obtenerFechaActual());
        ADOHistorialEstado adohi = new ADOHistorialEstado();
        adohi.cerrarAccionActualizarHistorial(he);
    }
    public void abrirAccionNuevoHistorial(Accion a, Usuario usu){        
        HistorialEstado he = new HistorialEstado();
        he.setIdAccion(a.getId());
        he.setFechaInicio(obtenerFechaActual());
        he.setEstado(1);
        he.setUsuario(usu);
        ADOHistorialEstado adohi = new ADOHistorialEstado();
        adohi.abrirAccionNuevoHistorial(he);
    }
     


    /* este metodo valida que no se ingresen dias como 32, o meses como 14 etc*/
    public void validarDiasMesFecha(String fecha) throws FechaIncorrectaException {
        String decenaDia = String.valueOf(fecha.charAt(0));
        String unidadDia = String.valueOf(fecha.charAt(1));
        String decenaMes = String.valueOf(fecha.charAt(3));
        String unidadMes = String.valueOf(fecha.charAt(4));
        String[] splitFecha = fecha.split("-"); // tomo el ,es, para ver si es febrero y validar diferente

        if (Integer.valueOf(splitFecha[1]) == 2) {// si el mes es 2 es febrero
            if ((Integer.parseInt(decenaDia) > 2) || (Integer.parseInt(unidadDia) > 8 && Integer.parseInt(decenaDia) <= 2)) {
                throw new FechaIncorrectaException();
            }
        } else {
            if (Integer.parseInt(decenaDia) > 3 || Integer.parseInt(decenaMes) > 1
                    || (Integer.parseInt(decenaDia) == 3 && Integer.parseInt(unidadDia) > 1) || (Integer.parseInt(decenaMes) == 1 && Integer.parseInt(unidadMes) > 2)) {
                throw new FechaIncorrectaException();
            }
        }
    }
    
    public Date obtenerFechaActual() {
        java.util.Date fecha = new Date();
        return fecha;
    }

    public void validarLongitudFecha(String fecha) throws FechaIncorrectaException {
        if (fecha.length() < 10) {
            throw new FechaIncorrectaException();
        }
    }
    
}
